using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using System.Text;
using System.Web;

namespace Pegasus.Diagnostics
{
	/// <summary>
	/// This class is used to build the dump strings for verious .NET objects.
	/// </summary>
	internal class TraceDumper
	{
		/// <summary>
		/// Get the formated string of the filename and
		/// </summary>
		/// <param name="stackFrame">The stack frame the represents the calling point on the stack</param>
		/// <returns>A string with the filename and the line number of the calling method</returns>
		public static string GetCallingMethod( StackFrame stackFrame )
		{
			string filename = Path.GetFileName( stackFrame.GetFileName() );

			MethodBase methodBase = stackFrame.GetMethod();
			if( methodBase == null )
			{
				return "unknown method name";
			}

			if( filename == null || filename.Length == 0 )
			{
				return methodBase.ToString();
			}
			else
			{
				return string.Format( "{0} in {1}:{2}", 
					methodBase.ToString(),
					filename,
					stackFrame.GetFileLineNumber() );
			}
		}

		/// <summary>
		/// Dumps the exception to the debug stream.
		/// </summary>
		/// <param name="level">Stack level of the source code</param>
		/// <param name="e">The exception to dump.</param>
		/// <param name="messageFormat">A message to display containing zero or more format items.</param>
		/// <param name="args">An object array containing zero or more objects to format.</param>
		/// <returns>A string with all the object information in it.</returns>
		public static string BuildDumpException( int level, Exception e, string messageFormat, params object[] args )
		{
			StringBuilder except = new StringBuilder();
 
			// If we have a string add it to the string
			if( messageFormat != null && messageFormat.Length > 0 )
			{
				except.AppendFormat( messageFormat, args );
				except.Append( "\n" );
			}

			except.AppendFormat( "Exception type {0} at {1}", 
				e.GetType().Name,
				GetCallingMethod( new StackFrame( level, true ) ) );
			except.Append( "\n" );

			except.Append( "Message: " ).Append( e.Message ).Append( "\n" )
				.Append( "Source: " ).Append( e.Source ).Append( "\n" )
				.Append( "Stack:" ).Append( "\n" ).Append( e.StackTrace ).Append( "\n" );

			// Dump the inner exceptions
			Exception inner = e.InnerException;
			while( inner != null )
			{
				except.Append( "Inner exception type " ).Append( inner.GetType().Name ).Append( "\n" )
					.Append( "Message: " ).Append( inner.Message ).Append( "\n" )
					.Append( "Source: " ).Append( inner.Source ).Append( "\n" )
					.Append( "Stack:" ).Append( "\n" ).Append( inner.StackTrace ).Append( "\n" );

				inner = inner.InnerException;
			}

			return except.ToString();
		}

		/// <summary>
		/// Dumps the web request
		/// </summary>
		/// <param name="request">The request to dump.</param>
		/// <returns>A string with all the object information in it.</returns>
		public static string BuildDumpWebRequest( HttpRequest request )
		{
			StringBuilder text = new StringBuilder();

			text.AppendFormat( "HttpRequest Type:  {0}\n", request.GetType().ToString() );
			text.AppendFormat( "ContentLength:     {0}\n", request.ContentLength );
			text.AppendFormat( "ContentType:       {0}\n", request.ContentType );
			text.AppendFormat( "HttpMethod:        {0}\n", request.HttpMethod );
			text.AppendFormat( "RawUrl:            {0}\n", request.RawUrl );

			return text.ToString();
		}

		/// <summary>
		/// Dumps the web response 
		/// </summary>
		/// <param name="response">The response to dump.</param>
		/// <returns>A string with all the object information in it.</returns>
		public static string BuildDumpWebResponse( HttpResponse response )
		{
			StringBuilder text = new StringBuilder();

			text.AppendFormat( "HttpRequest Type:  {0}\n", response.GetType().ToString() );
			text.AppendFormat( "ContentType:       {0}\n", response.ContentType );
			text.AppendFormat( "StatusCode:        {0}\n", response.StatusCode );
			text.AppendFormat( "Status:            {0}\n", response.Status );
			text.AppendFormat( "StatusDescription: {0}\n", response.Status );

			return text.ToString();
		}
	}
}
